// OGoMojo
// Whitemice.MOGI.Document
// License: LGPL
// Copyright: Whitemice Consulting, 2006
// Author(s): Adam Tauno Williams (awilliam@whitemice.org)
using System;
using System.Collections;
using log4net;

namespace Whitemice.MOGI
{
	/// \param Abstract helper implementation of a document class,  does not implement IDocument
	public abstract class Document
	{
		protected	IServer 		iserver;
		
		/// \brief Constructor
		/// \param server
		public Document(IServer server) 
		{
			this.iserver = server;		
			Log.Debug("Document(MOGI.IServer)");
		}
		
		/// \brief Return name of object
		public abstract string Name { get; }
		
		/// \brief Indicate if the object is writable by the current actor
		/// \note You should check if AccessCheck operation is supported first
		public bool Writable
		{
			get { return iserver.AllowsWrite(this.Name); }
		}
		
		/// \brief Return type of document, uses the Name property
		public DocumentType Type 
		{
			get 
			{
				return MOGI.DetermineType(this.Name);
			}
		}		
		
		/// \brief Indicate if the server supports operation on this type of document
		public bool SupportsOperation(Operation operation)
		{
			return iserver.SupportsOperation(this.Type, operation);
		}
		
		/// \brief Grant specified right to specified actor
		/// \param actorId
		/// \param operation
		public void GrantRight(string actorId, string operation)
		{
			bool write;
			bool read;
			write = false;
			read = false;
			if (operation.IndexOf('r') > 0) read = true;
			if (operation.IndexOf('w') > 0) write = true;
			GrantRight(actorId, write, read); 
		}
		
		/// \brief Return arraylist of assigned rights
		/// \note You should check if AccessList operation is supported on this document
		public ArrayList Rights
		{
			get
			{
				return iserver.Rights(this.Name);
			}
		}
		
		/// \brief Check if the specified actor can perform the specified operation
		/// \param actorId
		/// \param operation
		/// \note You should check if AccessList operation is supported on this document
		public bool HasRight(string actorId, string operation)
		{
			return iserver.HasRight(actorId, this.Name, operation);
		}

		/// \brief Check if the specified actor can perform the specified operation
		/// \param actorId
		/// \note You should check if AccessList operation is supported on this document
		public bool HasRead(string actorId)
		{
			return HasRight(actorId, "r");
		}

		/// \brief Check if the specified actor can perform the specified operation
		/// \param actorId
		/// \note You should check if AccessList operation is supported on this document		
		public bool HasWrite(string actorId)
		{
			return HasRight(actorId, "w");
		}		

		/// \brief Give the specified right to the specified actor
		/// \param actorId
		/// \param write
		/// \param read
		/// \note You should check if AccessGrant operation is supported on this document		
		public void GrantRight(string actorId, bool write, bool read)
		{
			iserver.SetRight(this.Name, actorId, write, read);
		}

		/// \brief Give the specified right to the specified actor
		/// \param right
		/// \note You should check if AccessGrant operation is supported on this document				
		public void GrantRight(Rights right)
		{
			GrantRight(right.Holder, right.Write, right.Read);
		}

		/// \brief Give the specified rights to the specified actor
		/// \param rights
		/// \note You should check if AccessGrant operation is supported on this document						
		public void GrantRights(ArrayList rights)
		{
			foreach(Rights right in rights)
				GrantRight(right.Holder, right.Write, right.Read);
		}

		/// \brief Give the specified rights to the specified actor
		/// \param rights
		/// \note You should check if AccessGrant operation is supported on this document						
		public void GrantRights(Rights[] rights)
		{
			foreach(Rights right in rights)
				GrantRight(right.Holder, right.Write, right.Read);
		}
		
		public IServer Server
		{
			get { return iserver; }
		}
		
		public ILog Log
		{ 
			get { return iserver.Log; } 
		}
		
		public event DocumentModifiedDelegate Modified;		
		
		protected void Changed(string key, object v1, object v2)
		{
			if(v1.ToString() == v2.ToString())
			{
				if(!(Modified == null))
				{
					DocumentModifiedArgs args = new DocumentModifiedArgs();
					Modified(this, args);
				}
			}
		}			
	}
}
